package com.wbpay.pay.utils;

import android.content.Context;
import android.content.Intent;
import android.os.StrictMode;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;

import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class Utils {

    private static String sCallbackAction = null;
    private static String sPackageName = null;

    /**
     * 将单位分的金额转换成单位元的金额（315->3.15）
     *
     * @param fee 待转换的金额
     * @return String 已被转换的金额
     */
    public static String convertFenToYuan(String fee) {
        return String.valueOf(new BigDecimal(fee).divide(new BigDecimal("100"),
                2, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 获取手机ip地址
     */
    public static String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface
                    .getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf
                        .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()
                            && (inetAddress instanceof Inet4Address)) {

                        return inetAddress.getHostAddress().toString();
                    }
                }
            }
        } catch (SocketException e) {
        }

        return null;
    }

    public static String getRandom32() {
        String strRand = "";
        for (int i = 0; i < 32; i++) {
            strRand += String.valueOf((int) (Math.random() * 10));
        }

        return strRand;
    }

    public static void wxgfPay(Context context, Map<String, String> params) {
        String res = Utils.sendPost(Constants.WXGF_GET_ORDER_ID,
                createXml(params), 4000);
        if (!TextUtils.isEmpty(res)) {
            String prepay_id = readerXmlForDOM(res);
            if (!TextUtils.isEmpty(prepay_id)) {
                callWechatForPay(context, prepay_id, Constants.APP_ID, Constants.PARTNER_ID, Constants.API_KEY);
            } else {
                sendPayResult(context, -1, Utils.getString(context, "pay_request_order_fail"));
            }
        } else {
            sendPayResult(context, -1, Utils.getString(context, "pay_request_order_fail"));
        }
    }

    /**
     * 唤起微信支付，此函数可以直接接受服务器的参数
     * @param context
     * @param prepay_id
     * @param appId
     * @param partnerId
     * @param apiKey
     */
    private static void callWechatForPay(Context context, String prepay_id,
                            String appId, String partnerId, String apiKey) {
        // 调起微信支付
        IWXAPI api = WXAPIFactory.createWXAPI(context, appId);
        api.registerApp(appId);
        String nonceStr = getRandom32();
        String timeStamp = getSecondTimestamp(new Date()) + "";

        PayReq req = new PayReq();

        req.appId = appId;
        req.partnerId = partnerId;
        req.prepayId = prepay_id;
        req.packageValue = "Sign=WXPay";
        req.nonceStr = nonceStr;
        req.timeStamp = timeStamp;

        Map<String, String> pm = new HashMap<String, String>();
        pm.put("appid", appId);
        pm.put("partnerid", partnerId);
        pm.put("prepayid", prepay_id);
        pm.put("package", "Sign=WXPay");
        pm.put("noncestr", nonceStr);
        pm.put("timestamp", timeStamp);
        req.sign = EncryptUtil.getMD5(
                formatUrlMap(pm, false, false) + "&key="
                        + apiKey).toUpperCase();
        api.sendReq(req);
    }

    public static String createXml(Map<String, String> params) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            XmlSerializer xml = Xml.newSerializer();
            xml.setOutput(baos, "UTF-8");
            xml.startTag(null, "xml");
            Set set = params.entrySet();
            Iterator it = set.iterator();

            while (it.hasNext()) {
                Map.Entry<String, String> me = (Map.Entry<String, String>) it
                        .next();
                String key = me.getKey();
                String value = me.getValue();
                if (value != null) {
                    xml.startTag(null, key);
                    xml.text(value);
                    xml.endTag(null, key);
                }
            }

            xml.startTag(null, "sign");
            xml.text(EncryptUtil.getMD5(formatUrlMap(params, false, false)
                    + "&key=" + Constants.API_KEY).toUpperCase());
            xml.endTag(null, "sign");

            xml.endTag(null, "xml");
            xml.endDocument();

            byte[] xmlData = baos.toByteArray();
            String xmlString = new String(xmlData, "UTF-8");
            baos.flush();
            baos.close();
            baos = null;
            return xmlString;

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String sendPost(String postUrl, String params, int timeout) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads().detectDiskWrites().detectNetwork() // or
                // .detectAll()
                // for
                // all
                // detectable
                // problems
                .penaltyLog().build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath()
                .build());
        StringBuffer resultString = new StringBuffer();
        String currentLineString;
        OutputStreamWriter out;
        InputStream urlInputStream = null;
        BufferedReader bufferedReader = null;
        try {

            URL url = new URL(postUrl);
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(timeout);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
            out = new OutputStreamWriter(connection.getOutputStream());
            out.write(params);
            out.flush();
            out.close();
            urlInputStream = connection.getInputStream();
            bufferedReader = new BufferedReader(new InputStreamReader(
                    urlInputStream, "UTF-8"));
            while ((currentLineString = bufferedReader.readLine()) != null) {
                resultString.append(currentLineString);
            }
        } catch (MalformedURLException e) {
            // logger.error(e.getCause(), e);
        } catch (IOException e) {
            // logger.error(e.getCause(), e);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    // logger.error(e.getCause(), e);
                }
            }
            if (urlInputStream != null) {
                try {
                    urlInputStream.close();
                } catch (IOException e) {
                    // logger.error(e.getCause(), e);
                }
            }
        }
        return resultString.toString();
    }

    public static String formatUrlMap(Map<String, String> paraMap,
                                      boolean urlEncode, boolean keyToLower) {
        String buff = "";
        Map<String, String> tmpMap = paraMap;
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
                    tmpMap.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds,
                    new Comparator<Map.Entry<String, String>>() {

                        @Override
                        public int compare(Map.Entry<String, String> o1,
                                           Map.Entry<String, String> o2) {
                            return (o1.getKey()).toString().compareTo(
                                    o2.getKey());
                        }
                    });
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (isNotBlank(item.getKey())) {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlEncode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    if (keyToLower) {
                        buf.append(key.toLowerCase() + "=" + val);
                    } else {
                        buf.append(key + "=" + val);
                    }
                    buf.append("&");
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            return null;
        }
        Log.d("njsdk", "buff : " + buff);
        return buff;
    }

    public static boolean isNotBlank(String src) {
        return null != src && (!"".equals(src.trim()));
    }

    public static String readerXmlForDOM(String params) {

        try {

            String return_code = "";
            ;
            String result_code = "";
            String prepay_id = "";

            DocumentBuilderFactory factory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(
                    params)));

            Element root = doc.getDocumentElement();
            NodeList books = root.getChildNodes();
            if (books != null) {
                for (int i = 0; i < books.getLength(); i++) {
                    Node book = books.item(i);

                    if (book.getNodeName().equals("return_code")) {
                        return_code = book.getFirstChild().getNodeValue();
                    }

                    if (book.getNodeName().equals("result_code")) {
                        result_code = book.getFirstChild().getNodeValue();
                    }

                    if (book.getNodeName().equals("prepay_id")) {
                        prepay_id = book.getFirstChild().getNodeValue();
                    }

                }
            }

            if (return_code.equals("SUCCESS") && result_code.equals("SUCCESS")) {
                return prepay_id;

            } else {
                return "";
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 获取精确到秒的时间戳
     *
     * @param date
     * @return
     */
    public static int getSecondTimestamp(Date date) {
        if (null == date) {
            return 0;
        }
        String timestamp = String.valueOf(date.getTime() / 1000);
        return Integer.valueOf(timestamp);
    }

    /**
     * 使用gb2312编码将字符串转换成字节序列
     *
     * @param string 待转换的字符串
     * @return byte[] 字节序列
     */
    public static byte[] getBytes(String string) {
        return getBytes(string, "UTF-8");
    }

    /**
     * 使用指定编码将字符串转换成字节序列；编码为空或null值则使用系统默认编码。
     *
     * @param string  待转换的字符串
     * @param charset 指定编码
     * @return byte[] 字节序列
     */
    public static byte[] getBytes(String string, String charset) {
        if (isBlankOrNull(charset)) {
            return string.getBytes();
        }
        try {
            return string.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException(
                    "System doesn't support the character encoding! [charset="
                            + charset + "][string=" + string + "]");
        }
    }

    public static boolean isBlankOrNull(String str) {
        if (str == null || str.equals("") || str.equals("null")) {
            return true;
        } else {
            return false;
        }
    }

    public static void setCallback(String s) {
        sCallbackAction = s;
    }

    public static void setPackage(String s) {
        sPackageName = s;
    }

    public static void sendPayResult(Context context, int error, String desc) {
        Log.d("njsdk", "callbackAction : " + sCallbackAction);
        Intent intent = new Intent(sCallbackAction);
        intent.putExtra("RESULT_CODE", error);
        intent.putExtra("RESULT_DESC", desc);
        intent.setPackage(sPackageName);
        context.sendBroadcast(intent);
    }

    public static String getString(Context context, String resource) {
        int strId = context.getResources().getIdentifier(resource, "string", context.getPackageName());
        if (strId > 0) {
            return context.getResources().getString(strId);
        }
        return null;
    }
}
